﻿
using H.Controls.Dock.Layout;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Input;

namespace H.Controls.Dock.Controls
{
    /// <summary>
    /// Implements the content part of the document control.
    /// It hosts a <see cref="LayoutDocument"/> as its <see cref="Model"/>.
    /// </summary>
    public class LayoutDocumentControl : System.Windows.Controls.Control
    {
        #region Constructors

        /// <summary>
        /// Static class constructor
        /// </summary>
        static LayoutDocumentControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(LayoutDocumentControl), new FrameworkPropertyMetadata(typeof(LayoutDocumentControl)));
            FocusableProperty.OverrideMetadata(typeof(LayoutDocumentControl), new FrameworkPropertyMetadata(true));
        }

        #endregion Constructors

        #region Properties

        #region Model

        /// <summary><see cref="Model"/> dependency property.</summary>
        public static readonly DependencyProperty ModelProperty = DependencyProperty.Register(nameof(Model), typeof(LayoutContent), typeof(LayoutDocumentControl),
          new FrameworkPropertyMetadata(null, OnModelChanged));

        /// <summary>
        /// Gets or sets the <see cref="Model"/> property.
        /// This dependency property indicates the model attached to this view.
        /// </summary>
        public LayoutContent Model
        {
            get => (LayoutContent)GetValue(ModelProperty);
            set => SetValue(ModelProperty, value);
        }

        /// <summary>Handles changes to the <see cref="Model"/> property.</summary>
        private static void OnModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((LayoutDocumentControl)d).OnModelChanged(e);

        /// <summary>Provides derived classes an opportunity to handle changes to the <see cref="Model"/> property.</summary>
        protected virtual void OnModelChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.OldValue != null) ((LayoutContent)e.OldValue).PropertyChanged -= Model_PropertyChanged;
            if (this.Model != null)
            {
                this.Model.PropertyChanged += Model_PropertyChanged;
                SetLayoutItem(this.Model?.Root?.Manager?.GetLayoutItemFromModel(this.Model));
            }
            else
                SetLayoutItem(null);
        }

        private void Model_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName != nameof(LayoutContent.IsEnabled)) return;
            if (this.Model == null) return;
            this.IsEnabled = this.Model.IsEnabled;
            if (this.IsEnabled || !this.Model.IsActive) return;
            if (this.Model.Parent is LayoutDocumentPane layoutDocumentPane) layoutDocumentPane.SetNextSelectedIndex();
        }

        #endregion Model

        #region LayoutItem

        /// <summary><see cref="LayoutItem"/> Read-Only dependency property.</summary>
        private static readonly DependencyPropertyKey LayoutItemPropertyKey = DependencyProperty.RegisterReadOnly(nameof(LayoutItem), typeof(LayoutItem), typeof(LayoutDocumentControl),
          new FrameworkPropertyMetadata(null));

        public static readonly DependencyProperty LayoutItemProperty = LayoutItemPropertyKey.DependencyProperty;

        /// <summary>
        /// Gets the <see cref="LayoutItem"/> property. This dependency property
        /// indicates the LayoutItem attached to this tag item.
        /// </summary>
        public LayoutItem LayoutItem => (LayoutItem)GetValue(LayoutItemProperty);

        /// <summary>
        /// Provides a secure method for setting the <see cref="LayoutItem"/> property.
        /// This dependency property indicates the LayoutItem attached to this tag item.
        /// </summary>
        /// <param name="value">The new value for the property.</param>
        protected void SetLayoutItem(LayoutItem value) => SetValue(LayoutItemPropertyKey, value);

        #endregion LayoutItem

        #endregion Properties

        #region Overrides

        /// <inheritdoc />
        protected override void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e)
        {
            Debug.WriteLine($"{nameof(OnPreviewMouseLeftButtonUp)}: {this.LayoutItem.ContentId}");
            SetIsActive();
            base.OnPreviewMouseLeftButtonUp(e);
        }

        /// <inheritdoc />
        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            SetIsActive();
            base.OnMouseLeftButtonDown(e);
        }

        /// <inheritdoc />
        protected override void OnMouseRightButtonDown(MouseButtonEventArgs e)
        {
            SetIsActive();
            base.OnMouseLeftButtonDown(e);
        }

        #endregion Overrides

        #region Private Methods

        private void SetIsActive()
        {
            if (this.Model != null && !this.Model.IsActive) this.Model.IsActive = true;
        }

        #endregion Private Methods
    }
}